package KademliaDht

import(
	"os"
	"rpc"
	"strconv"
)

// Node identifier.
// In Kademlia a node is identified by is ID, IP and port number.
type KadContact struct {
	Id		uint64
	Ip 		string
	Port	int
}

// The sender of the STORE RPC provides a key and a block of data and requires that the recipient store the data and make it available for later retrieval by that key.
// This is a primitive operation, not an iterative one.
// The result is a boolean indicating weather the key allready existed or not. If it allready existed, the value is replaced.
func ( kc *KadContact ) Store ( me *KadContact, key uint64, value []byte ) ( existed bool, error os.Error ) {	
	client, error := rpc.Dial( "tcp", kc.Ip + ":" + strconv.Itoa( kc.Port ) )
	defer client.Close()
	if error != nil {
		return false, error
	}

	var callRes bool
	error = client.Call( "KadNode.Store", new_KadKeyValue ( me, key, value ), &callRes )
	if error != nil {
		return false, error
	}
	
	return callRes, nil
}

// The FIND_NODE RPC includes a 160-bit key. The recipient of the RPC returns up to k triples (IP address, port, nodeID) for the contacts that it knows to be closest to the key.
// The recipient must return k triples if at all possible. It may only return fewer than k if it is returning all of the contacts that it has knowledge of.
// This is a primitive operation, not an iterative one.
func ( kc *KadContact ) Find_Node ( me *KadContact, key uint64 ) ( ks []*KadContact, error os.Error ) {
	client, error := rpc.Dial( "tcp", kc.Ip + ":" + strconv.Itoa( kc.Port ) )
	defer client.Close()
	if error != nil {
		return nil, error
	}

	callRes := new_KadFindNodeResult ( nil )
	error = client.Call( "KadNode.Find_Node", new_KadKeyWrapper( me, key ), callRes )
	if error != nil {
		return nil, error
	}
	
	return callRes.Nodes, nil
}

// A FIND_VALUE RPC includes a B=160-bit key (64 bit in our case). If a corresponding value is present on the recipient, the associated data is returned. Otherwise the RPC is equivalent to a FIND_NODE and a set of k triples is returned.
// This is a primitive operation, not an iterative one.
func ( kc *KadContact ) Find_Value ( me *KadContact, key uint64 ) ( value []byte, ks []*KadContact, error os.Error ) {
	client, error := rpc.Dial( "tcp", kc.Ip + ":" + strconv.Itoa( kc.Port ) )
	defer client.Close()
	if error != nil {
		return nil, nil, error
	}

	callRes := new_KadFindValueResult ( nil,  nil )
	error = client.Call( "KadNode.Find_Value", new_KadKeyWrapper( me, key ), callRes )
	if error != nil {
		return nil, nil, error
	}
	
	if callRes.Value != nil {
		return callRes.Value, nil, nil
	}
	
	return nil, callRes.Nodes, nil
}

